<?php
/**
 * 后台panx职员的管理
 * Author: lyun
 * Date: 2018/3/24
 * Time: 11:35
 * Created by panxsoft.
 */

namespace App\Http\Controllers\Admin\Panx\StaffManage;

use App\Http\Controllers\ApiController;
use App\Http\Middleware\AdminAuth;
use App\Http\Requests\Admin\Panx\StaffManage\PanxStaffIndexRequest;
use App\Http\Requests\Admin\Panx\StaffManage\PanxStaffOperateRequest;
use App\Http\Requests\Admin\Panx\StaffManage\PanxStaffStoreRequest;
use App\Http\Requests\Admin\Panx\StaffManage\PanxStaffUpdateRequest;
use App\Models\Admin\PanxAdmin;
use App\Services\Locale\Language;
use App\Services\Utils\ApiChecker;
use App\Services\Utils\ApiResponser;
use App\Services\Utils\Guard;
use App\Services\Utils\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Models\Admin\Role;

class PanxStaffController extends ApiController
{
    const ROUTES = [
        'index' => 'api.admin.panx.staff.index',
        'store' => 'api.admin.panx.staff.store',
        'update' => 'api.admin.panx.staff.update',
        'patch' => 'api.admin.panx.staff.patch',
    ];

    /**
     * Display a listing of the resource.
     * @test
     *
     * @param PanxStaffIndexRequest $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function index(PanxStaffIndexRequest $request)
    {
        $this->checkIsTrue(PanxAdmin::checkIsSuperMan(), trans('admin.is_super_man'));

        // 显示所有，除了自己
        $panx_admin = PanxAdmin::filterIsSuperMan()
            ->columnsKeywordsOrLike([
                'name'    => $request->keyword,
                'account' => $request->keyword,
                'email'   => $request->keyword,
                'phone'   => $request->keyword,
            ])
            ->with('roles')
            ->orderBy($request->order_by ?: 'created_at', $request->sort ?: 'desc')
            ->paginate($request->per_page ?: 15);

        return $this->response(compact('panx_admin'));
    }

    /**
     *  返回管理员的角色信息
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $roles = Role::where('guard_name', PanxAdmin::GUARD_NAME)
            ->where('is_deleted', Role::ROLE_IS_NOT_DELETED)
            ->get(['id', Language::getLocalNameColumn()]);

        return $this->response(compact('roles'));
    }

    /**
     * Store a newly created resource in storage.
     * @test
     *
     * @param  PanxStaffStoreRequest $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(PanxStaffStoreRequest $request)
    {
        // 超管才能添加的
        $this->checkIsTrue(PanxAdmin::checkIsSuperMan(), trans('admin.is_super_man'));

        $panx_admin = $this->assembleStaffStoreData($request);
        $role_name = $this->getChineseRole($request->role_name);

        $stored = Transaction::handle(function () use ($role_name, $panx_admin) {

            /** @var PanxAdmin $panx */
            $panx = PanxAdmin::create($panx_admin);

            $panx->assignRole($role_name);

            return $panx;
        });

        return $this->response(compact('stored'));
    }

    /**
     * 职员更新自己 和 超管更新员工的接口
     * @test
     *
     * @param  PanxStaffUpdateRequest $request
     * @param  int $id
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function update(PanxStaffUpdateRequest $request, $id)
    {
        /** @var PanxAdmin $panx_admin */
        $panx_admin = PanxAdmin::find($id);
        $this->checkItemExist($panx_admin, trans('admin.panx_admin'));

        $panx_admin_data = $this->assembleStaffStoreData($request);

        $is_super_man = PanxAdmin::checkIsSuperMan();
        $is_update_self = (Guard::panxAdmin()->id === (int)$id);

        if ($is_update_self) { // 职员更新自己，没有更新权限

            $updated = $panx_admin->update($panx_admin_data);

        } else if ($is_super_man) {  // 超管更新员工的信息

            $updated = $this->updatePanxStaff($panx_admin, $panx_admin_data, $request->role_name);
        } else {

            $this->checkIsTrue(false, trans('admin.illegality_panx_admin'));
        }

        $panx_admin = $panx_admin->load('roles');

        return $this->response(compact('updated', 'panx_admin'));
    }

    /**
     * @deprecated - 暂时不删除数据，只有启用和禁用
     * Remove the specified resource from storage.
     *
     * @param  int $id
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function destroy($id)
    {
        $panxAdmin = Guard::panxAdmin();

        $this->checkIsTrue($id !== $panxAdmin->id, '管理员不能删除自己');
        $this->checkIsTrue($panxAdmin->isSuperMan(), '只有管理员能删除员工');

        /** @var PanxAdmin $staff */
        $staff = PanxAdmin::find($id);
            $this->checkIsTrue($staff, '错误的管理员ID');

        $deleted = $staff->delete();

        return $this->response(compact('deleted'));
    }

    /**
     * 启用和禁用后台管理员
     * @test
     *
     * @param PanxStaffOperateRequest $request
     * @param $staff_id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function patchEnabled(PanxStaffOperateRequest $request, $staff_id)
    {
        // 超管才能操作的
        $this->checkIsTrue(PanxAdmin::checkIsSuperMan(), trans('admin.is_super_man'));

        // 不能禁用第一个超管
        $first_panx_admin = PanxAdmin::oldest()->first();
        $this->checkUnless($first_panx_admin->id === (int)$staff_id, trans('admin.first_panx_admin'));

        /** @var PanxAdmin $panx_admin */
        $panx_admin = PanxAdmin::find($staff_id);
        $this->checkItemExist($panx_admin, trans('admin.panx_admin'));

        $updated = $panx_admin->update(['is_deleted' => $request->is_deleted]);

        return $this->response(compact('updated', 'panx_admin'));
    }

    /**
     * @param PanxStaffStoreRequest|PanxStaffUpdateRequest|Request $request
     * @return array
     */
    private function assembleStaffStoreData(Request $request)
    {
        $data = [
            'panx_id' => Guard::panxAdmin()->panx_id,
            'name'    => $request->name,
            'email'   => $request->email,
            'account' => $request->account,
            'phone'   => $request->phone,
            'sex'     => $request->sex,
            'born_at' => $request->born_at ?? Carbon::now(),
        ];

        if ($request->password) {
            $data['password'] = $request->password;
        }

        return $data;
    }

    /**
     * @param $role_name
     * @return null
     * @throws \Exception
     */
    private function getChineseRole($role_name)
    {
        $language = app()->getLocale();

        if ($language === Language::EN) {
            $role_name = isset(PanxAdmin::ROLE_RELATION[$role_name])
                ? PanxAdmin::ROLE_RELATION[$role_name]
                : null;
            $this->checkIsTrue($role_name, trans('admin.role_name'));
        }

        return $role_name;
    }

    /**
     * @param PanxAdmin $panx_admin
     * @param array $panx_admin_data
     * @param $role_name
     *
     * @return mixed
     * @throws \Exception
     */
    private function updatePanxStaff(PanxAdmin $panx_admin, array $panx_admin_data, $role_name)
    {
        $updated = Transaction::handle(function () use ($panx_admin, $panx_admin_data, $role_name) {

            $this->editStaffRole($panx_admin, $role_name);

            $updated = $panx_admin->update($panx_admin_data);

            return $updated;
        });

        return $updated;
    }

    /**
     * @param PanxAdmin $panx_admin
     * @param $role_name
     * @return bool
     * @throws \Exception
     */
    private function editStaffRole(PanxAdmin $panx_admin, $role_name)
    {
        if (! $role_name) return false;
        $role_name = $this->getChineseRole($role_name);

        //不能修改第一个超管的角色
        $oldest_panx_admin = PanxAdmin::oldest()
            ->first();

        $admin_is_oldest = $oldest_panx_admin->id === $panx_admin->id;
        $admin_had_role = $panx_admin->hasRole($role_name);

        if ($admin_is_oldest) {
            $this->checkIsTrue($admin_had_role, trans('admin.edit_first_panx_admin'));
            return false;
        }

        $panx_admin->syncRoles($role_name);
        return true;
    }
}
